package full

import (
	"errors"
	"fmt"
	"db2s/Dm"
	"db2s/Gr"
	"db2s/Ms"
	"db2s/My"
	"db2s/Or"
	"db2s/ref"
	"reflect"
	"strings"
)

var (
	GolMeMap = map[string]any{
		"mysql":     My.GolF{},
		"oracle":    Or.GolF{},
		"cluster":   Gr.GolF{},
		"dm":        Dm.GolF{},
		"sqlserver": Ms.GolF{},
	}
	sumMeMap = map[string]any{
		"mysql":     My.SumF{},
		"oracle":    Or.SumF{},
		"cluster":   Gr.SumF{},
		"dm":        Dm.SumF{},
		"sqlserver": Ms.SumF{},
	}
	rowsMeMap = map[string]any{
		"mysql":     My.RowsF{},
		"oracle":    Or.RowsF{},
		"cluster":   Gr.RowsF{},
		"dm":        Dm.RowsF{},
		"sqlserver": Ms.RowsF{},
	}
	dmlMeMap = map[string]any{
		"mysql":   My.DmlF{},
		"oracle":  Or.DmlF{},
		"cluster": Dm.DmlF{},
		"dm":      Dm.DmlF{},
	}
)

func NewGolStatus(drive string) (res GolEr, err error) {
	var e any
	if e, err = driveCheck(GolMeMap, drive); err != nil {
		return
	}
	switch e.(type) {
	case My.GolF:
		res = e.(My.GolF)
	//case Dm.GolF:
	//	res = e.(Dm.GolF)
	//case Gr.GolF:
	//	res = e.(Gr.GolF)
	case Or.GolF:
		res = e.(Or.GolF)
	//case Ms.GolF:
	//	res = e.(Ms.GolF)
	default:
		err = ref.ErrAddPrintf("NewGolStatus", errors.New(fmt.Sprintf("type not match. curry type is %v", reflect.TypeOf(e))))
		return
	}
	return
}

func NewFull(drive []string, join, role string) Full {
	return Full{Drive: drive, Role: role, Join: join}
}
func NewFullSum(drive string) (res SumEr, err error) {
	var e any
	if e, err = driveCheck(sumMeMap, drive); err != nil {
		return
	}
	switch e.(type) {
	case My.SumF:
		res = e.(My.SumF)
	//case Dm.SumF:
	//	res = e.(Dm.SumF)
	//case Gr.SumF:
	//	res = e.(Gr.SumF)
	case Or.SumF:
		res = e.(Or.SumF)
	//case Ms.SumF:
	//	res = e.(Ms.SumF)
	default:
		err = ref.ErrAddPrintf("Full.NewFullSum", errors.New(fmt.Sprintf("type not match. curry type is %v", reflect.TypeOf(e))))
		return
	}
	return
}
func NewFullRows(drive string) (res RowsEr, err error) {
	var e any
	if e, err = driveCheck(rowsMeMap, drive); err != nil {
		err = ref.ErrAddPrintf("Full.NewFullRows", err)
		return
	}
	switch e.(type) {
	case My.RowsF:
		res = e.(My.RowsF)
	//case Dm.RowsF:
	//	res = e.(Dm.RowsF)
	//case Gr.RowsF:
	//	res = e.(Gr.RowsF)
	case Or.RowsF:
		res = e.(Or.RowsF)
	//case Ms.RowsF:
	//	res = e.(Ms.RowsF)
	default:
		err = ref.ErrAddPrintf("Full.NewFullRows", errors.New(fmt.Sprintf("type not match. curry type is %v", reflect.TypeOf(e))))
		return
	}
	return
}
func joinResult(join string, obj []any) (res any) {
	switch join {
	case "left":
		return obj[0]
	case "right":
		if len(obj) == 1 {
			return obj[0]
		}
		return obj[1]
	case "join":
		return obj
	}
	return
}

func driveCheck(driveMap map[string]any, name string) (e any, err error) {
	var ok bool
	e, ok = driveMap[name]
	if ok {
		return
	}
	err = errors.New(fmt.Sprintf("input database type error. input is {%v} What is expected is {%v}", name, func() string {
		var p []string
		for k := range driveMap {
			p = append(p, k)
		}
		return strings.Join(p, ",")
	}()))
	return
}
func joinExec(join string, k int) bool {
	switch {
	case strings.EqualFold(join, "left") && k == 1:
		return true
	case strings.EqualFold(join, "right") && k == 0:
		return true
	}
	return false
}
